package xyz.xtt.asset.service.impl;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Redirect;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import com.tongtong.middleware.client.BlockchainClient;
import com.tongtong.middleware.vo.params.AccountParams;
import com.tongtong.middleware.vo.response.AccountResponse;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import xyz.xtt.asset.constants.AssetConstants;
import xyz.xtt.asset.constants.ErrorMessage;
import xyz.xtt.asset.entity.TblAssetGroup;
import xyz.xtt.asset.entity.TblAssetGroupMember;
import xyz.xtt.asset.request.CreateGorupRequest;
import xyz.xtt.asset.request.JoinGroupRequest;
import xyz.xtt.asset.response.CreateGorupResponse;
import xyz.xtt.asset.response.ResponseResult;
import xyz.xtt.asset.service.ITblAssetGroupMemberService;
import xyz.xtt.asset.service.ITblAssetGroupService;
import xyz.xtt.asset.service.IThirdService;
import xyz.xtt.asset.vo.AddGroupMaxMemberCountResponse;
import xyz.xtt.asset.vo.CommonResponse;
import xyz.xtt.asset.vo.CreateGorupResult;
import xyz.xtt.common.asset.AssertUtils;
import xyz.xtt.common.response.ApiResult;

@RefreshScope
@Slf4j
@Service
public class ThirdServiceImpl implements IThirdService {
	@Autowired
	private ITblAssetGroupService iTblAssetGroupService;
	@Autowired
	private ITblAssetGroupMemberService iTblAssetGroupMemberService;
	@Value("${user.createGroup.requestUrl}")
	private String createGroupRequestUrl;

	@Value("${user.joinGroup.requestUrl}")
	private String joinGroupRequestUrl;

	@Value("${user.checkfriend.requestUrl}")
	private String checkFriendRequestUrl;

	@Value("${user.info.thirdAuthCode}")
	private String thirdAuthCode;

	@Value("${user.info.addGroupMaxMemberCountUrl}")
	private String addGroupMaxMemberCountUrl;

	@Autowired
	private BlockchainClient blockchainClient;

	@Override
	public AccountResponse createAndQueryAccount(AccountParams req) {
		ApiResult<AccountResponse> createAndQueryAccount = blockchainClient.createAndQueryAccount(req);
		log.info("createAndQueryAccount response: {}", JSONUtil.toJsonStr(createAndQueryAccount));
		return ApiResult.convert(createAndQueryAccount, null);
	}

	private HttpResponse<String> post(String requestUrl, String jsonStr) {
		HttpRequest request = HttpRequest
				.newBuilder()
				.uri(URI.create(requestUrl))
				.header(AssetConstants.AUTHORIZATION, thirdAuthCode)
				.header("Content-Type", "application/json")
				.timeout(Duration.ofSeconds(10))
				.POST(HttpRequest.BodyPublishers.ofString(jsonStr, StandardCharsets.UTF_8))
				.build();
		try {
			HttpClient client = HttpClient.newHttpClient();
			HttpResponse<String> send = client.send(request, HttpResponse.BodyHandlers.ofString());
			return send;
		} catch (IOException | InterruptedException e) {
			log.info("post body:{}, ex:{}", jsonStr, e.getMessage(), e);
		}
		return null;
	}

	@Override
	public Boolean checkFriend(Long assetId, Long from, Long to) {
		HttpClient client = HttpClient.newBuilder().followRedirects(Redirect.NORMAL).connectTimeout(Duration.ofSeconds(30)).version(Version.HTTP_1_1).build();
		String url = String.format(checkFriendRequestUrl, from, to);
		HttpRequest request = HttpRequest
				.newBuilder()
				.uri(URI.create(url))
				.header(AssetConstants.AUTHORIZATION, thirdAuthCode)
				.timeout(Duration.ofSeconds(30))
				.GET()
				.build();
		try {
			HttpResponse<String> send = client.send(request, HttpResponse.BodyHandlers.ofString());
			int statusCode = send.statusCode();
			log.info("checkFriend assetId:{} url:{},send.statusCode:{}", assetId, checkFriendRequestUrl, statusCode);
			String body = send.body();
			ResponseResult<Boolean> bean = JSONUtil.toBean(body, new TypeReference<ResponseResult<Boolean>>() {
			}, false);
			AssertUtils.isNull(bean, ErrorMessage.CHECK_FRIEND_EX);
			log.info("checkFriend assetId:{} url:{},send.body:{}", assetId, checkFriendRequestUrl, body);

			if (Objects.equals(bean.getData(), Boolean.TRUE)) {
				return Boolean.TRUE;
			}
		} catch (Exception e) {
			log.info("checkFriend from:{},to:{} ex:{}", from, to, e.getMessage(), e);
			return false;
		}
		return false;
	}

	@Override
	public CreateGorupResult createGorup(Long assetId, Long orderId, Long masterId, String groupName) {
		String grpName = groupName.length() > 16 ? groupName.substring(0, 16) : groupName;
		CreateGorupRequest body = CreateGorupRequest.builder().masterId(masterId).groupName(grpName).typeId(String.valueOf(assetId)).groupType(3).build();
		HttpResponse<String> post = post(createGroupRequestUrl, JSONUtil.toJsonStr(body));
		int statusCode = post.statusCode();
		log.info("createGorup body :{}", JSONUtil.toJsonStr(body));
		log.info("createGorup orderId:{} url:{},send.statusCode:{}", orderId, createGroupRequestUrl, statusCode);
		String responseText = post.body();
		log.info("createGorup orderId:{} url:{},send.responseText:{}", orderId, createGroupRequestUrl, responseText);
		ResponseResult<CreateGorupResponse> bean = JSONUtil.toBean(responseText, new TypeReference<ResponseResult<CreateGorupResponse>>() {
		}, false);
		AssertUtils.isNull(bean, ErrorMessage.CREATE_GROUP_EX);
		CreateGorupResponse data = bean.getData();
		long grpId = IdUtil.getSnowflakeNextId();
		TblAssetGroup group = TblAssetGroup
				.builder()
				.id(grpId)
				.assetId(assetId)
				.state(1)
				.transactionOrderId(orderId)
				.thirdGroupName(grpName)
				.thirdGroupId(data.getGroupId())
				.crt(LocalDateTime.now())
				.crtId(masterId)
				.thirdRequestStart(LocalDateTime.now())
				.thirdRequestStatus(statusCode)
				.thirdRequestResponse(responseText)
				.build();
		boolean save = iTblAssetGroupService.save(group);
		// 群主入群记录
		TblAssetGroupMember groupMember = TblAssetGroupMember
				.builder()
				.id(grpId)
				.transactionOrderId(orderId)
				.groupId(grpId)
				.state(1)
				.uid(masterId)
				.thirdGroupId(data.getGroupId())
				.crt(LocalDateTime.now())
				.crtId(masterId)
				.thirdRequestStart(LocalDateTime.now())
				.thirdRequestStatus(statusCode)
				.thirdRequestResponse(responseText)
				.build();
		boolean saveMember = iTblAssetGroupMemberService.save(groupMember);
		boolean b = bean.isOK() && save && saveMember;
		return CreateGorupResult.builder().result(b).group(group).groupMember(groupMember).build();
	}

	@Override
	public Boolean joinGroup(Long orderId, Long from, Long groupId, String thirdGroupId, Long userId, Integer source) {
		JoinGroupRequest body = JoinGroupRequest.builder().groupId(thirdGroupId).userId(userId).build();
		HttpResponse<String> post = post(joinGroupRequestUrl, JSONUtil.toJsonStr(body));
		int statusCode = post.statusCode();
		log.info("joinGroup orderId:{} url:{},statusCode:{}", orderId, joinGroupRequestUrl, statusCode);
		String responseText = post.body();
		log.info("joinGroup orderId:{} url:{},responseText:{}", orderId, joinGroupRequestUrl, responseText);
		ResponseResult<CreateGorupResponse> bean = JSONUtil.toBean(responseText, new TypeReference<ResponseResult<CreateGorupResponse>>() {
		}, false);
		AssertUtils.isNull(bean, ErrorMessage.CREATE_GROUP_EX);
		TblAssetGroupMember groupMember = TblAssetGroupMember
				.builder()
				.id(IdUtil.getSnowflakeNextId())
				.transactionOrderId(orderId)
				.groupId(groupId)
				.thirdGroupId(thirdGroupId)
				.crt(LocalDateTime.now())
				.crtId(from)
				.state(1)
				.uid(userId)
				.thirdRequestStart(LocalDateTime.now())
				.thirdRequestStatus(statusCode)
				.thirdRequestResponse(responseText)
				.joinSource(source)
				.build();
		boolean save = iTblAssetGroupMemberService.save(groupMember);
		return bean.isOK() && save;
	}

	@Override
	public CommonResponse addGroupMaxMemberCount(Long uid) {
		String targetUid = String.valueOf(uid);
		String requestUrl = addGroupMaxMemberCountUrl + targetUid;
		HttpRequest request = HttpRequest
				.newBuilder()
				.uri(URI.create(requestUrl))
				.header(AssetConstants.AUTHORIZATION, thirdAuthCode)
				.timeout(Duration.ofSeconds(10))
				.GET()
				.build();
		String body = StringUtils.EMPTY;
		try {
			HttpClient client = HttpClient.newHttpClient();
			HttpResponse<String> send = client.send(request, HttpResponse.BodyHandlers.ofString());
			int statusCode = send.statusCode();
			body = send.body();
			log.info("addGroupMaxMemberCount requestUrl:{},uid:{},statusCode:{},body:{}", requestUrl, uid, statusCode, body);
			if (Objects.equals(200, statusCode)) {
				AddGroupMaxMemberCountResponse bean = JSONUtil.toBean(body, AddGroupMaxMemberCountResponse.class);
				return CommonResponse.builder().result(bean.isOk()).param(JSONUtil.toJsonStr(Map.of(uid, uid))).thirdResponse(JSONUtil.toJsonStr(bean)).build();
			}
		} catch (IOException | InterruptedException e) {
			log.info("addGroupMaxMemberCount ex uid:{}, ex:{}", uid, e.getMessage(), e);
		}
		AddGroupMaxMemberCountResponse fail = AddGroupMaxMemberCountResponse.fail();
		return CommonResponse.builder().result(Boolean.FALSE).param(JSONUtil.toJsonStr(Map.of(uid, uid))).thirdResponse(JSONUtil.toJsonStr(fail)).build();
	}
}
